// ValidationAspects
// Written by Mike Saunders
// Released under Microsoft Public License (Ms-PL)
using System;
using NUnit.Framework;
using ValidationAspects.Exceptions;
using ValidationAspects.Factories;

namespace TestValidationAspects.Factories
{
	[TestFixture]
	public class TestLengthInRange
	{
		private static void Fail(int min, int max, string actual)
		{
			Test.Throws<ValidateLengthInRangeException>(() => new LengthInRange {Minimum = min, Maximum = max}.Create<string>().Invoke(actual, new MockValidationContext()),
			                                            new ValidateLengthInRangeException(min, max, actual.Length).Message);
		}

		private static void Pass(int min, int max, string actual)
		{
			new LengthInRange {Minimum = min, Maximum = max}.Create<string>().Invoke(actual, new MockValidationContext());
		}

		[Test]
		public void Test_CreateValidator_throws_when_min_is_not_less_than_max()
		{
			Test.Throws<ArgumentOutOfRangeException>(() => new LengthInRange {Minimum = 0, Maximum = 0}.Create<string>(),
			                                         new ArgumentOutOfRangeException("Minimum", string.Format("Range minimum must be less than maximum [value:{0}].", 0)).Message);
			Test.Throws<ArgumentOutOfRangeException>(() => new LengthInRange {Minimum = 1, Maximum = 0}.Create<string>(),
			                                         new ArgumentOutOfRangeException("Minimum", string.Format("Range minimum must be less than maximum [value:{0}].", 0)).Message);
		}

		[Test]
		public void Test_LengthInRange()
		{
			Fail(2, 4, "a");
			Pass(2, 4, "aa");
			Pass(2, 4, "aaa");
			Pass(2, 4, "aaaa");
			Fail(2, 4, "aaaaa");
		}

		[Test]
		public void Test_LengthInRange_on_empty_string()
		{
			Fail(2, 4, string.Empty);
			Pass(0, 4, string.Empty);
		}

		[Test]
		public void Test_validation_skips_null_value()
		{
			Pass(2, 4, null);
		}
	}
}